/**
 * @ProjectName: go-learn-demo
 * @PackageName: _2_relation
 * @Description: 自定义中间表
 * @Author: hy.bai
 * @Date: 2025-08-05 18:10
 */
package m2mtable

import (
	"encoding/json"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"time"
)

// 实现多对多的功能:创建两个关联的结构体
// 在Mysql中，实现多对多功能是创建一个中间表。
// 定义Person结构体

type Person struct {
	Id      uint `gorm:"primary"` // 定义主键
	Name    string
	Address []*Address `gorm:"many2many:person_addrs"` // 定义多对多的关系(生成中间表),并指定中间表的表名。
}

// 定义Address结构体
type Address struct {
	Id       uint      `gorm:"primary"` // 定义主键
	AddrName string    // 具体的地址
	Person   []*Person `gorm:"many2many:person_addrs"` // 定义多对多的关系(生成中间表),并指定中间表的表名。
}

// 自定义中间表
type PersonAddr struct {
	PersonID  uint `gorm:"primaryKey"`
	AddressID uint `gorm:"primaryKey"`
	CreatedAt time.Time
	DeletedAt gorm.DeletedAt
}

// 自定义多对多的中间表
func TestCustomTable() {
	// 1.连接数据库
	dns := "root:root@tcp(127.0.0.1:3308)/test?charset=utf8mb4&parseTime=True&loc=Local"
	// 定义全局配置
	gConfig := &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	}
	db, err := gorm.Open(mysql.Open(dns), gConfig)
	if err != nil {
		panic(fmt.Sprintf("连接数据库失败,失败原因是:%s\n", err.Error()))
	} else {
		fmt.Printf("连接的数据库是:%s", db.Name()) // mysql:表示数据库连接成功
	}

	// 2.判断数据库表是否存在，如果不存在，则创建
	//person := &Person{}
	//if !db.Migrator().HasTable(person) {
	//	db.AutoMigrate(person)
	//}
	//addr := &Address{}
	//if !db.Migrator().HasTable(addr) {
	//	db.AutoMigrate(addr)
	//}
	//// 自定义创建第三张表。且第三张表，需要强制创建
	//db.AutoMigrate(&PersonAddr{})

	// 多对多的关系的新增
	// createPerson(db)

	personPreload(db)

	fmt.Println("数据库初始化执行完毕~~~")
}

// 创建用户
func createPerson(db *gorm.DB) {
	person := &Person{
		Name: "lp",
		Address: []*Address{
			{
				AddrName: "河南驻马店",
			},
			{
				AddrName: "河南郑州",
			},
		},
	}
	db.Create(person)
}

// 预加载
func personPreload(db *gorm.DB) {
	var persons []Person
	db.Preload("Address").Find(&persons)
	pBytes, _ := json.Marshal(persons)
	fmt.Printf("查询结果是:%s\n", string(pBytes))
}
